#include <stdio.h>
#include <iostream>
#include <assert.h>
#include <string>        //字符串
#include <unordered_set> //哈希集合

using namespace std;
//  abacde
/*3. 无重复字符的最长子串*/
int lengthOfLongestSubstring(string s)
{
    int length = s.length();
    int j = 0;
    int i = 0;
    int k = 1;
    string key = "";
    while (i <= length - 1)
    {
        int n = k - i;
        key = s.substr(i, n);
        // 切下一个字符
        string keylast = s.substr(i + n, 1);
        if (keylast == "")
        {
            break;
        }
        // 对比已切字符是否有重复
        while (j <= key.length() - 1)
        {
            if (keylast != key.substr(j, 1))
            {
                // 不重复继续比较
                j++;
            }
            else
            {
                // 下一个字符有重复
                i++;
                k = i + 1;
                break;
            }
        }
        if (j == key.length())
        {
            k++;
            j = 0;
        }
    }
    string finkey = "";
    int x = max(finkey.length(), key.length());
    finkey = key;
    printf("%s\n", finkey.c_str());
    return x;
}
int ss(string s)
{
    // 哈希集合，记录每个字符是否出现过
    unordered_set<char> occ;
    int n = s.size();
    // 右指针，初始值为 -1，相当于我们在字符串的左边界的左侧，还没有开始移动
    int rk = -1, ans = 0;
    // 枚举左指针的位置，初始值隐性地表示为 -1
    for (int i = 0; i < n; ++i)
    {
        if (i != 0)
        {
            // 左指针向右移动一格，移除一个字符
            occ.erase(s[i - 1]);
        }
        while (rk + 1 < n && !occ.count(s[rk + 1]))
        {
            // 不断地移动右指针
            occ.insert(s[rk + 1]);
            ++rk;
        }
        // 第 i 到 rk 个字符是一个极长的无重复字符子串
        ans = max(ans, rk - i + 1);
    }
    return ans;
}
int main()
{
    string str = "abcabcbb";
    // int length = lengthOfLongestSubstring(str);
    int length = ss(str);
    printf("%d\n", length);
    return length;
}